package dev.ece.suit.loader.models.dae;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import dev.ece.util.lib.Matrix4f;
import dev.ece.util.tools.Constants;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="library_controllers")
public class DAEControllers {

	@XmlElement
	private Controller[] controller;
	
	public Map<String, Controller> toControllerMap() {
		Map<String, Controller> map = new ConcurrentHashMap<String, Controller>();
		if(controller != null) {
			for(Controller controller: this.controller) {
				map.put(StringUtils.join("#", controller.getId()), controller);
			}
		}
		return map;
	}
	
	public Controller[] getController() {
		return controller;
	}

	public void setController(Controller[] controller) {
		this.controller = controller;
	}

	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="controller")
	public static class Controller {
		
		@XmlAttribute
		private String id;
		
		@XmlElement
		private Skin skin;

		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public Skin getSkin() {
			return skin;
		}

		public void setSkin(Skin skin) {
			this.skin = skin;
		}
		
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="skin")
	public static class Skin {
		
		@XmlAttribute(name = "source")
		private String id;
		
		@XmlElement
		private String bind_shape_matrix;
		
		@XmlElement
		private DAEGeometries.Source[] source;
		
		@XmlElement
		private Joints joints;
		
		@XmlElement
		private VertexWeights vertex_weights;
		
		public Map<String, DAEGeometries.Source> createSourceMap() {
			Map<String, DAEGeometries.Source> sources = new ConcurrentHashMap<String, DAEGeometries.Source>();
			if(source != null) {
				for(DAEGeometries.Source source: this.source) {
					sources.put(StringUtils.join("#", source.getId()),  source);
				}
			}
			return sources;
		}

		public Matrix4f toBindShapeMatrix() {
			if(StringUtils.isNotBlank(bind_shape_matrix)) {
				String[] array = StringUtils.split(StringUtils.trim(bind_shape_matrix), " ");
				float[] matrix = new float[16];
				for(int i=0; i<matrix.length; i++) {
					matrix[i] = NumberUtils.toFloat(array[i]);
				}
				return new Matrix4f(matrix);
			}
			Matrix4f result = new Matrix4f();
			result.identity();
			return result;
		}
		
		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public String getBind_shape_matrix() {
			return bind_shape_matrix;
		}

		public void setBind_shape_matrix(String bind_shape_matrix) {
			this.bind_shape_matrix = bind_shape_matrix;
		}

		public DAEGeometries.Source[] getSource() {
			return source;
		}

		public void setSource(DAEGeometries.Source[] source) {
			this.source = source;
		}

		public Joints getJoints() {
			return joints;
		}

		public void setJoints(Joints joints) {
			this.joints = joints;
		}

		public VertexWeights getVertex_weights() {
			return vertex_weights;
		}

		public void setVertex_weights(VertexWeights vertex_weights) {
			this.vertex_weights = vertex_weights;
		}
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="joints")
	public static class Joints {
		
		@XmlElement
		private DAEGeometries.Input[] input;

		public DAEGeometries.Input[] getInput() {
			return input;
		}

		public void setInput(DAEGeometries.Input[] input) {
			this.input = input;
		}
	}
	
	@XmlAccessorType(XmlAccessType.FIELD)
	@XmlRootElement(name="vertex_weights")
	public static class VertexWeights {
		
		@XmlAttribute
		private int count;
		
		@XmlElement
		private DAEGeometries.Input[] input;
		
		@XmlElement
		private String vcount;
		
		@XmlElement
		private String v;
		
		public int[] toIntArray(String content) throws IOException {
			String[] array = StringUtils.split(StringUtils.trim(Constants.inline(content).toString()), " ");
			int[] result = new int[array.length];
			for(int i=0; i<array.length; i++) {
				result[i] = NumberUtils.toInt(array[i]);
			}
			return result;
		}
		
		public int[] toVArray() throws IOException {
			return toIntArray(this.v);
		}
		
		public int[] toVCountArray() throws IOException {
			return toIntArray(this.vcount);
		}
		
		public int getCount() {
			return count;
		}

		public void setCount(int count) {
			this.count = count;
		}

		public DAEGeometries.Input[] getInput() {
			return input;
		}

		public void setInput(DAEGeometries.Input[] input) {
			this.input = input;
		}

		public String getVcount() {
			return vcount;
		}

		public void setVcount(String vcount) {
			this.vcount = vcount;
		}

		public String getV() {
			return v;
		}

		public void setV(String v) {
			this.v = v;
		}
		
	}
	
}
